﻿using System;
using System.IO;
using System.Net;
using System.Runtime.Serialization.Formatters.Binary;
using System.ServiceModel.Syndication;
using System.Text;
using System.Windows.Media.Imaging;
using System.Xml;
using NCMIS.ObjectModel.Rest;

namespace Ncmis.Client.Explorer.DELETE
{
    /// <summary>
    /// 
    /// </summary>
    class CmisWebRequest
    {
        #region Properties

        public string Password
        {
            get;
            set;
        }

        public Uri Uri
        {
            get;
            set;
        }

        public string UserName
        {
            get;
            set;
        }

        #endregion

        /// <summary>
        /// Instatiates a new instance of <see cref="NCMIS.Client.CmisWebRequest"/>.
        /// </summary>
        /// <param name="userName">The username.</param>
        /// <param name="password">The password.</param>
        /// <param name="serviceDocumentUri">The service document URI.</param>
        public CmisWebRequest(string userName, string password, Uri serviceDocumentUri)
        {
            this.UserName = userName;
            this.Password = password;
            this.Uri = serviceDocumentUri;
        }

        /// <summary>
        /// Serializes an object graph into a byte array.
        /// </summary>
        /// <param name="objectGraph"></param>
        /// <returns></returns>
        //private static byte[] ToByteArray(Object objectGraph)
        //{

        //    SyndicationItemFormatter formatter = new Atom10ItemFormatter(new SyndicationItem());
        //    StringBuilder builder = new StringBuilder();
        //    using (XmlWriter writer = XmlWriter.Create(builder))
        //    {
        //        formatter.WriteTo(writer);
        //    }

        //    System.Diagnostics.Debug.WriteLine(builder);
           
        //    byte[] bytes = null;
        //    try
        //    {
        //        MemoryStream memoryStream = new MemoryStream();
        //        BinaryFormatter binaryFormatter = new BinaryFormatter();
        //        binaryFormatter.Serialize(memoryStream, objectGraph);
        //        bytes = memoryStream.GetBuffer();
        //    }
        //    catch (Exception ex)
        //    {
        //        System.Diagnostics.Debug.WriteLine(ex.Message);
        //    }
        //    return bytes;
        //}

        private byte[] ToByteArray(SyndicationItem entry)
        {
            StringBuilder builder = new StringBuilder();
            SyndicationItemFormatter formatter = new Atom10ItemFormatter(entry);
            using (XmlWriter writer = XmlWriter.Create(builder))
            {
                formatter.WriteTo(writer);
            }

            string objectGraph = builder.ToString();

            byte[] bytes = null;
            try
            {
                MemoryStream memoryStream = new MemoryStream();
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                binaryFormatter.Serialize(memoryStream, objectGraph);
                bytes = memoryStream.GetBuffer();
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
            return bytes;
        }

        public SyndicationItem InvokeSyndicationFeed(string uri, string method)
        {
            SyndicationItem result = null;
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(uri);
                request.Credentials = new NetworkCredential(UserName, Password);
                request.Method = method;

                var response = (HttpWebResponse)request.GetResponse();
                result = ConvertResponseToSyndicationItem(response);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        // default method POST (alt. PUT, DELETE)
        public SyndicationItem InvokeSyndicationFeed(string uri, SyndicationItem entry)
        {
            byte[] content = ToByteArray(entry);

            SyndicationItem result = null;
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(uri);
                request.Credentials = new NetworkCredential(UserName, Password);
                request.Method = "POST";
                request.ContentLength = content.Length;
                request.ContentType = CmisContentType.Entry;
                using (Stream requestStream = request.GetRequestStream())
                {
                    requestStream.Write(content, 0, content.Length);
                }
     
                // The server returns status code: 400 Bad request 
                var response = (HttpWebResponse)request.GetResponse();
                result = ConvertResponseToSyndicationItem(response);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        public SyndicationFeed GetSyndicationFeed(string uri)
        {
            SyndicationFeed result = null;
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(uri);
                request.Credentials = new NetworkCredential(UserName, Password);
                request.Method = "GET";

                var response = (HttpWebResponse)request.GetResponse();
                result = ConvertResponseToSyndicationFeed(response);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return result;
        }

        public Stream GetContent(Uri uri)
        {
            Stream stream = null;
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(uri);
                request.Credentials = new NetworkCredential(UserName, Password);
                request.Method = "GET";
                var response = (HttpWebResponse)request.GetResponse();
                stream = response.GetResponseStream();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return stream;
        }

        public ServiceDocument GetServiceDocument()
        {
            ServiceDocument serviceDocument = null;
            try
            {
                var request = (HttpWebRequest)WebRequest.Create(Uri);
                request.Credentials = new NetworkCredential(UserName, Password); // NEW
                request.Method = "GET";
                //SetBody(request, requestBody);

                var response = (HttpWebResponse)request.GetResponse();

                serviceDocument = ConvertResponseToServiceDocument(response);
                
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return serviceDocument;
        }


        private ServiceDocument ConvertResponseToServiceDocument(HttpWebResponse response)
        {
            string[] contentTypes;
            string[] contentTypes2;
            ServiceDocument serviceDocument = null;

            contentTypes = response.Headers.GetValues("Content-Type");
            contentTypes2 = contentTypes[0].Split(';');
            using (XmlReader reader = XmlReader.Create(response.GetResponseStream()))
            {
                try
                {
                    if (contentTypes[0].Equals(CmisContentType.Service) || contentTypes2[0].Equals(CmisContentType.Service))
                    {
                        serviceDocument = ServiceDocument.Load(reader);
                    }
                }
                catch (XmlException ex)
                {
                    throw ex;
                }
            }

            return serviceDocument;
        }

        private SyndicationItem ConvertResponseToSyndicationItem(HttpWebResponse response)
        {
            return null;
        }

        private SyndicationFeed ConvertResponseToSyndicationFeed(HttpWebResponse response)
        {
            string[] contentTypes;
            //string[] contentTypes2;
            SyndicationFeed feed = null;

            contentTypes = response.Headers.GetValues("Content-Type");
            //contentTypes2 = contentTypes[0].Split(';');
            using (XmlReader reader = XmlReader.Create(response.GetResponseStream()))
            {
                try
                {
                    // There may be more text attached to end of content type string
                    if (contentTypes[0].StartsWith(CmisContentType.Feed))
                    //if (contentTypes[0].Equals(CmisContentType.Feed) || contentTypes2[0].Equals(CmisContentType.Feed))
                    {
                        feed = SyndicationFeed.Load(reader);
                    }
                }
                catch (XmlException ex)
                {
                    throw ex;
                }
            }

            return feed;
        }
    }
}